'use strict';
import { STORE } from '../constant.js';
import { dataHandler } from '../utils/index.js';

class LeeStore extends App.Event {
  constructor(options = {}) {
    super();
    const {
      state = {},
      methods = {},
      lifetimes = {},
    } = options;

    if (!state.theme) {
      state.theme = 'blue';
    }
    
    this[STORE.STATE] = state;
    this[STORE.METHODS] = methods;
    this[STORE.LIFETIMES] = lifetimes;
  }

  commit(options = {}) {
    const newObj = Object.keys(options).reduce((map, key) => {
      dataHandler(key, options[key], this[STORE.STATE]);
      return map[`$state.${key}`] = options[key], map;
    }, {});
    this.emit('commit', newObj);
  }

  get state() {
    return JSON.parse(JSON.stringify(this[STORE.STATE]));
  }
}

export default (options = {}) => {
  return function(app) {
    const event = this;
    const store = new LeeStore(options);

    event.on('page/onLoad', page => {
      if (page.useStore === false) return ;
      const commitHandler = obj => page.setData(obj);
      event.once(page.$Event.onUnload, () => {
        store.off('commit', commitHandler);
      });
      store.on('commit', commitHandler);
      page.$store = store;
      page.setData({ $state: store[STORE.STATE] });
      for (const name in store[STORE.METHODS]) {
        if (name in page) continue;
        page[name] = store[STORE.METHODS][name];
      }
    });

    event.on('component/attached', self => {
      if (self.useStore === false) return;
      const commitHandler = obj => self.setData(obj);
      event.once(self.$Event.detached, () => {
        store.off('commit', commitHandler);
      });
      store.on('commit', commitHandler);
      self.$store = store;
      self.setData({ $state: store[STORE.STATE] });
    });

    app.$store = store;
  };
};
